######################################################
# Program-specific Variables
######################################################

# Directory where any object file libraries will be copied
OUTLIBDIR=../lib

# Directory where final executable will be stored
OUTDIR=../bin

# List of all C source files
SRCS=filesys.c memory.c misc.c process.c queue.c synch.c traps.c sysproc.c

# List of all assembly source files for the operating system
# (Note: usertraps.s is not part of the operating system)
ASMSRCS=osend.s trap_random.s dlxos.s

# List of os header files
HDRS=dlx.h dlxos.h filesys.h memory.h process.h queue.h synch.h syscall.h traps.h ostraps.h
OSHDRS=$(HDRS:%.h=os/%.h)

# List of assembly libraries to expose to user programs
BUILDLIBS=usertraps.aso misc.o
OUTLIBS=$(BUILDLIBS:%=$(OUTLIBDIR)/%)

# Any external object file libraries that should be linked with executable
LIBS=share_memory.o
FINALLIBS=$(LIBS:%.o=$(OUTLIBDIR)/%.o)

# Name of final executable
EXEC=os.dlx.obj

# Automatically-generated list of C object files from source files
OBJS=$(SRCS:%.c=%.o)

# Automatically-generated list of ASM object files from source files
ASMOBJS=$(ASMSRCS:%.s=%.aso)


######################################################
# Compiler-specific variables
######################################################

# Name of C compiler
CC=gcc-dlx

# Name of assembler
AS=dlxasm

# Flags passed to all invocations of C compiler
CFLAGS= -mtraps -Wall

# Flags for compiler indicating search path for include files
INCDIR= -I../include -I../include/os

# Flags sent to the assembler
ASFLAGS= -i _osinit


######################################################
# Bookkeeping Variables
######################################################

# Final result of program
OUTPUT=$(OUTDIR)/$(EXEC)

# Location of scratch space to store object and other intermediate files
WORKDIR=work

# Intermediate DLX file passed from C compiler to Assembler
OUTDLX=$(EXEC:%.dlx.obj=$(WORKDIR)/%.dlx)

# LST file generated by the Assembler, not used as a target
OUTLST=$(EXEC:%.dlx.obj=$(WORKDIR)/%.lst)

# Object files from C source with proper workdir location prepended
WORKOBJS=$(OBJS:%.o=$(WORKDIR)/%.o)

# Object files from ASM source with proper workdir location prepended
WORKASMOBJS=$(ASMOBJS:%.aso=$(WORKDIR)/%.aso)

# Headers translated to proper include directory
FINALHDRS=$(OSHDRS:%.h=../include/%.h)


#####################################################
# Targets and Dependencies
#####################################################

# Default target that is made when you type "make"
default: Makefile.depend $(WORKDIR) $(OUTDIR) $(OUTPUT) $(OUTLIBS)

# Builds dependencies for header files
Makefile.depend: $(SRCS) $(ASMSRCS) $(FINALHDRS)
	$(CC) $(INCDIR) -MM $(SRCS) $(ASMSRCS) | sed "s/^\(.*\):/$(WORKDIR)\/\1:/" > Makefile.depend
	usleep 50000

# Ensures directory for object files exists
$(WORKDIR):
	mkdir -p $@

# Ensures output directory exists
$(OUTDIR):
	mkdir -p $@

# Builds final output from DLX file using the assembler,
# then moves it to the final output directory
$(OUTPUT): $(OUTDLX)
	$(AS) $(ASFLAGS) -l $(OUTLST) $(OUTDLX)
	cp $(WORKDIR)/$(EXEC) $(OUTPUT)

# Builds DLX output file using the C compiler from all object files
$(OUTDLX): $(WORKOBJS) $(WORKASMOBJS) $(FINALIBS)
	$(CC) $(CFLAGS) $(INCDIR) -o $@ $(WORKOBJS) $(WORKASMOBJS) $(FINALLIBS)

# Builds any given object file from C source files
$(WORKDIR)/%.o:%.c
	$(CC) $(CFLAGS) $(INCDIR) -c -o $@ $<

# Builds any given object file from Assembly source files
$(WORKDIR)/%.aso:%.s
	$(CC) $(CFLAGS) $(INCDIR) -c -o $@ $<

# Builds any ASM library as an object file
$(OUTLIBDIR)/%o:$(WORKDIR)/%o
	cp $< $@

# Removes all intermediate files to force full rebuild
clean:
	-rm -rf $(WORKDIR) $(OUTPUT) $(OUTLIBS) Makefile.depend $(OUTDIR)/vm

# Changes to a given application and runs it via that app's Makefile
run:
	-cd ../apps/example; make run

# Includes added dependencies of source files on header files
include Makefile.depend
